#ifndef xpack_docker_stack
#define xpack_docker_stack
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::docker_stack::inc
#include"adapter/multi_push.hpp"
#include"define/base_type.hpp"
#include"docker/private/add.length.hpp"
#include"docker/private/single_linked_node.hpp"
#include"dumb/disable_copy.hpp"
#include"dumb/move.hpp"
#include"gc/self_management.hpp"
#include"macro/xexport.hpp"
#include"macro/xforward.hpp"
#include"macro/xitr_foreach.hpp"
#include"macro/xmodify.hpp"
#include"macro/xstruct.hpp"
#include"meta/has_constructor.hpp"
#include"utils/memory.hpp"
#include"utils/value_holder.hpp"
#pragma pop_macro("xuser")

namespace mixc::docker_stack{
    template<bool is_enable_length_v = true, inc::memory::is_allocator allocator_t = inc::memory::default_allocator_t>
    struct stack_conf{
        // 是否需要 length 这个属性
        template<bool is_enable_lengthx_v = is_enable_length_v>
        using set_is_enable_length = stack_conf<is_enable_lengthx_v>;

        // 设置分配器，需要符合 is_allocator 约束
        template<inc::memory::is_allocator default_allocatorx_t = allocator_t>
        using set_allocator = stack_conf<is_enable_length_v, default_allocatorx_t>;
    };

    template<class itemx_t, class conf_t = stack_conf<>>
    struct stack;

    #define xstack_conf_t       stack_conf<is_enable_length_v, default_allocator_t>

    template<
        class itemx_t,
        bool is_enable_length_v,
        inc::memory::is_allocator default_allocator_t
    >
    xstruct(
        xspec(stack, itemx_t, xstack_conf_t),
        xpubb(inc::add_length<is_enable_length_v>),
        xpubb(inc::multi_push<
            stack<itemx_t, xstack_conf_t>, itemx_t
        >),
        xpubb(inc::self_management),
        xpubb(inc::disable_copy),
        xprof(m_node, inc::single_linked_node_ptr<itemx_t>)
    )
        #undef  xstack_conf_t
    public:
        using inc::multi_push<the_t, itemx_t>::push;
        using item_t    = itemx_t;
    private:
        using value_t   = inc::value_holder<item_t>;
        using node_t    = inc::single_linked_node<item_t>;       // 纯节点类型
        using nodep     = node_t *;

        template<class guide>
        bool routing(){
            // TODO:==================================================
            throw;
        }

    public: // 属性区
        xprops()
            xpubget_pubsetx(top, item_t &){
                xr{
                    auto & cur = *xthe.m_node.top();
                    return cur;
                }
                xw{
                    auto & cur = *xthe.m_node.top();
                    (item_t &)cur = xforward(value);
                }

                xprops_operator_plus(*xthe.m_node.top(), item_t)
            };

            // 注意：
            // 多线程环境即使读取到的 stack::is_empty() 为 false 也不能确定该 stack 非空
            xpubgetx(is_empty, bool){
                xr{ return xthe.m_node.top() == nullptr; }
            };
        $

        xprops_operator()


    public: // 公有函数区
        stack() : 
            inc::add_length<is_enable_length_v>{},
            inc::multi_push<the_t, itemx_t>{},
            m_node{}{
        }

        // 构造析构区
        ~stack() {
            this->clear();
        }

        void clear() {
            nodep tmp;
            nodep cur = m_node.swap_top(nullptr);

            if constexpr (is_enable_length_v){
                xthe->length = 0;
            }

            while(cur != nullptr){
                tmp = cur;
                cur = cur->next;
                default_allocator_t::template free_with_destroy<node_t>(tmp);
            }
        }

        template<class forward_item_t>
        requires(inc::has_constructor<item_t, void(forward_item_t &&)>)
        void push(forward_item_t && value) {
            auto new_top    = default_allocator_t::template alloc<node_t>();
            xnew(new_top) node_t(xforward(value));

            new_top->next = m_node.swap_top(new_top);

            if constexpr (is_enable_length_v){
                xthe->length = xthe->length + 1;
            }
        }

        value_t pop() {
            if (nodep cur = m_node.top(); cur == nullptr){
                return {};
            }
            else{
                nodep free_item = cur;
                value_t r = inc::move(*cur);
                m_node.swap_top(cur->next);
                default_allocator_t::template free_with_destroy<node_t>(free_item);

                // cur != nullptr 有元素才可以计算
                if constexpr (is_enable_length_v){
                    xthe->length = xthe->length - 1;
                }
                return r;
            }
        }

        // 迭代器区
    private:
        template<auto mode_v, class interator_t>
        void foreach_template(interator_t invoke) const {
            nodep  cur   = m_node.top();
            uxx    index = 0;

            while(cur != nullptr){
                if (inc::itr_switch<mode_v>(xmodify(index), invoke, *cur) == loop_t::finish){
                    break;
                }
                cur = cur->next;
            }
        }

    public:
        xitr_foreach(item_t)
    $
}

namespace mixc::docker_stack::origin{
    using mixc::docker_stack::stack_conf;
    using mixc::docker_stack::stack;
}

#endif

xexport_space(mixc::docker_stack::origin)
